From 928c85ccc390bcd0285609373ea7859cfe072f10 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 26 May 2019 00:50:13 +0200 Subject: [PATCH] rendernodeparser: Parse Cairo nodes We also print the script, but we don't parse it yet. --- gsk/gskrendernode.h | 2 +- gsk/gskrendernodeimpl.c | 2 +- gsk/gskrendernodeparser.c | 138 +++++++++++++++--- testsuite/gsk/compare/empty-cairo.node | 1 + testsuite/gsk/compare/empty-cairo.png | Bin 0 -> 153 bytes testsuite/gsk/meson.build | 3 + testsuite/gsk/nodeparser/empty-cairo.node | 1 + testsuite/gsk/nodeparser/empty-cairo.ref.node | 5 + 8 files changed, 126 insertions(+), 26 deletions(-) create mode 100644 testsuite/gsk/compare/empty-cairo.node create mode 100644 testsuite/gsk/compare/empty-cairo.png create mode 100644 testsuite/gsk/nodeparser/empty-cairo.node create mode 100644 testsuite/gsk/nodeparser/empty-cairo.ref.node diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h index cdb59a46f4..79f0c6a059 100644 --- a/gsk/gskrendernode.h +++ b/gsk/gskrendernode.h @@ -189,7 +189,7 @@ GskRenderNode * gsk_cairo_node_new (const graphene_ GDK_AVAILABLE_IN_ALL cairo_t * gsk_cairo_node_get_draw_context (GskRenderNode *node); GDK_AVAILABLE_IN_ALL -const cairo_surface_t * gsk_cairo_node_peek_surface (GskRenderNode *node); +cairo_surface_t * gsk_cairo_node_peek_surface (GskRenderNode *node); GDK_AVAILABLE_IN_ALL GskRenderNode * gsk_container_node_new (GskRenderNode **children, diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index ec66c7f14b..32e5d57827 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -1582,7 +1582,7 @@ static const GskRenderNodeClass GSK_CAIRO_NODE_CLASS = { gsk_render_node_diff_impossible, }; -const cairo_surface_t * +cairo_surface_t * gsk_cairo_node_peek_surface (GskRenderNode *node) { GskCairoNode *self = (GskCairoNode *) node; diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c index ab7b3bd2a8..937e7d796f 100644 --- a/gsk/gskrendernodeparser.c +++ b/gsk/gskrendernodeparser.c @@ -33,6 +33,10 @@ #include "gtk/css/gtkcssdataurlprivate.h" #include "gtk/css/gtkcssparserprivate.h" +#ifdef CAIRO_HAS_SCRIPT_SURFACE +#include +#endif + typedef struct _Declaration Declaration; struct _Declaration @@ -768,6 +772,30 @@ parse_declarations (GtkCssParser *parser, return parsed; } +static GdkTexture * +create_default_texture (void) +{ + static const guint32 pixels[100] = { + 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0, + 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0, + 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0, + 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0, + 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, + 0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, + 0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, + 0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, + 0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC }; + GBytes *bytes; + GdkTexture *texture; + + bytes = g_bytes_new_static ((guchar *) pixels, 400); + texture = gdk_memory_texture_new (10, 10, GDK_MEMORY_DEFAULT, bytes, 40); + g_bytes_unref (bytes); + + return texture; +} + static GskRenderNode * create_default_render_node (void) { @@ -873,23 +901,7 @@ parse_texture_node (GtkCssParser *parser) parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); if (texture == NULL) - { - static const guint32 pixels[100] = { - 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0, - 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0, - 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0, - 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0, - 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, - 0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, - 0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, - 0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, - 0, 0, 0, 0, 0, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC, 0xFFFF00CC }; - GBytes *bytes = g_bytes_new_static ((guchar *) pixels, 400); - - texture = gdk_memory_texture_new (10, 10, GDK_MEMORY_DEFAULT, bytes, 40); - g_bytes_unref (bytes); - } + texture = create_default_texture (); node = gsk_texture_node_new (texture, &bounds); g_object_unref (texture); @@ -897,6 +909,44 @@ parse_texture_node (GtkCssParser *parser) return node; } +static GskRenderNode * +parse_cairo_node (GtkCssParser *parser) +{ + graphene_rect_t bounds = GRAPHENE_RECT_INIT (0, 0, 50, 50); + GdkTexture *pixels = NULL; + const Declaration declarations[] = { + { "bounds", parse_rect, NULL, &bounds }, + { "pixels", parse_texture, clear_texture, &pixels } + }; + GskRenderNode *node; + cairo_t *cr; + + parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + + node = gsk_cairo_node_new (&bounds); + + cr = gsk_cairo_node_get_draw_context (node); + + if (pixels != NULL) + { + cairo_surface_t *surface; + surface = gdk_texture_download_surface (pixels); + cairo_set_source_surface (cr, surface, 0, 0); + cairo_paint (cr); + cairo_surface_destroy (surface); + } + else + { + gdk_cairo_set_source_rgba (cr, &GDK_RGBA ("FF00CC")); + cairo_paint (cr); + } + + cairo_destroy (cr); + g_clear_object (&pixels); + + return node; +} + static GskRenderNode * parse_outset_shadow_node (GtkCssParser *parser) { @@ -1325,10 +1375,7 @@ parse_node (GtkCssParser *parser, { "debug", parse_debug_node }, { "blend", parse_blend_node }, { "repeat", parse_repeat_node }, -#if 0 { "cairo", parse_cairo_node }, -#endif - }; GskRenderNode **node_p = out_node; guint i; @@ -1696,9 +1743,9 @@ append_node_param (Printer *p, } static cairo_status_t -surface_write (void *closure, - const unsigned char *data, - unsigned int length) +cairo_write_array (void *closure, + const unsigned char *data, + unsigned int length) { g_byte_array_append (closure, data, length); @@ -1988,7 +2035,7 @@ render_node_print (Printer *p, surface = gdk_texture_download_surface (texture); array = g_byte_array_new (); - cairo_surface_write_to_png_stream (surface, surface_write, array); + cairo_surface_write_to_png_stream (surface, cairo_write_array, array); b64 = g_base64_encode (array->data, array->len); _indent (p); @@ -2170,6 +2217,49 @@ render_node_print (Printer *p, break; case GSK_CAIRO_NODE: + { + cairo_surface_t *surface = gsk_cairo_node_peek_surface (node); + GByteArray *array; + char *b64; + + start_node (p, "cairo"); + append_rect_param (p, "bounds", &node->bounds); + + array = g_byte_array_new (); + cairo_surface_write_to_png_stream (surface, cairo_write_array, array); + b64 = g_base64_encode (array->data, array->len); + + _indent (p); + g_string_append_printf (p->str, "pixels: url(\"data:image/png;base64,%s\");\n", b64); + + g_free (b64); + g_byte_array_free (array, TRUE); + +#ifdef CAIRO_HAS_SCRIPT_SURFACE + if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_RECORDING) + { + cairo_device_t *script; + + array = g_byte_array_new (); + script = cairo_script_create_for_stream (cairo_write_array, array); + + if (cairo_script_from_recording_surface (script, surface) == CAIRO_STATUS_SUCCESS) + { + b64 = g_base64_encode (array->data, array->len); + _indent (p); + g_string_append_printf (p->str, "script: url(\"data:;base64,%s\");\n", b64); + g_free (b64); + } + + cairo_device_destroy (script); + g_byte_array_free (array, TRUE); + } +#endif + + end_node (p); + } + break; + case GSK_REPEATING_LINEAR_GRADIENT_NODE: default: g_error ("Unhandled node: %s", node->node_class->type_name); diff --git a/testsuite/gsk/compare/empty-cairo.node b/testsuite/gsk/compare/empty-cairo.node new file mode 100644 index 0000000000..1987994306 --- /dev/null +++ b/testsuite/gsk/compare/empty-cairo.node @@ -0,0 +1 @@ +cairo { } diff --git a/testsuite/gsk/compare/empty-cairo.png b/testsuite/gsk/compare/empty-cairo.png new file mode 100644 index 0000000000000000000000000000000000000000..3a032a391ba59878cabf3e55f84ac5700bf00ff0 GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1SBWM%0B~AY)RhkE)4%caKYZ?lYt_Bo-U3d z5v^~}88RMFU^rkfqdv2OiMhJ!;6#lRcanR**KBA0zlCe9)9MRaL{NMO*_reMwH&H} PCNp@t`njxgN@xNAIEpo5 literal 0 HcmV?d00001 diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 4751dfd537..4f469603a9 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -27,6 +27,7 @@ compare_render_tests = [ 'empty-blend', 'empty-blur', 'empty-border', + 'empty-cairo', 'empty-clip', 'empty-color', 'empty-color-matrix', @@ -101,6 +102,8 @@ node_parser_tests = [ 'empty-blur.ref.node', 'empty-border.node', 'empty-border.ref.node', + 'empty-cairo.node', + 'empty-cairo.ref.node', 'empty-clip.node', 'empty-clip.ref.node', 'empty-color.node', diff --git a/testsuite/gsk/nodeparser/empty-cairo.node b/testsuite/gsk/nodeparser/empty-cairo.node new file mode 100644 index 0000000000..1987994306 --- /dev/null +++ b/testsuite/gsk/nodeparser/empty-cairo.node @@ -0,0 +1 @@ +cairo { } diff --git a/testsuite/gsk/nodeparser/empty-cairo.ref.node b/testsuite/gsk/nodeparser/empty-cairo.ref.node new file mode 100644 index 0000000000..4dca846961 --- /dev/null +++ b/testsuite/gsk/nodeparser/empty-cairo.ref.node @@ -0,0 +1,5 @@ +cairo { + bounds: 0 0 50 50; + pixels: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAABmJLR0QA/wD/AP+gvaeTAAAATklEQVRYhe3OMQHAIADAMJh/aXgCA3t6wZEoyNxjjfd8twP/tAqtQqvQKrQKrUKr0Cq0Cq1Cq9AqtAqtQqvQKrQKrUKr0Cq0Cq1Cq9AqDsEHAi9RKkB7AAAAAElFTkSuQmCC"); + script: url("data:;base64,JSFDYWlyb1NjcmlwdAo8PCAvY29udGVudCAvL0NPTE9SX0FMUEhBIC93aWR0aCA1MCAvaGVpZ2h0IDUwID4+IHN1cmZhY2UgY29udGV4dAoxIDAgMC44IHJnYiBzZXQtc291cmNlCnBhaW50CnBvcAo="); +} -- 2.30.2